package com.sqlcheck.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sqlcheck.dto.response.AIAnalysisResponse;
import com.sqlcheck.dto.response.AIStatementAnalysis;
import com.sqlcheck.dto.response.AIIssueDetail;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * AI响应解析工具类
 * 处理大模型返回的各种格式的JSON响应
 */
@Component
@Slf4j
public class AIResponseParser {

    private final ObjectMapper objectMapper = new ObjectMapper();
    
    // 匹配JSON代码块的正则表达式
    private static final Pattern JSON_CODE_BLOCK_PATTERN = Pattern.compile(
        "```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?```", 
        Pattern.MULTILINE | Pattern.DOTALL
    );
    
    // 匹配直接JSON的正则表达式
    private static final Pattern JSON_DIRECT_PATTERN = Pattern.compile(
        "\\{[\\s\\S]*\\}",
        Pattern.MULTILINE | Pattern.DOTALL
    );

    /**
     * 解析AI响应为统一的AIAnalysisResponse格式
     * 
     * @param rawResponse 原始AI响应
     * @return 解析后的AI分析响应
     */
    public AIAnalysisResponse parseAIResponse(String rawResponse) {
        log.debug("开始解析AI响应，原始长度: {}", rawResponse != null ? rawResponse.length() : 0);
        
        try {
            // 1. 提取JSON内容
            String jsonContent = extractJsonContent(rawResponse);
            if (jsonContent == null) {
                log.warn("无法从响应中提取有效的JSON内容");
                return createErrorResponse("无法解析AI响应：未找到有效的JSON格式");
            }
            
            log.debug("提取的JSON内容: {}", jsonContent.substring(0, Math.min(200, jsonContent.length())));
            
            // 2. 解析JSON为JsonNode
            JsonNode rootNode = objectMapper.readTree(jsonContent);
            
            // 3. 验证基本结构
            if (!rootNode.has("success") || !rootNode.has("statementAnalysis")) {
                log.warn("JSON结构缺少必要字段: success 或 statementAnalysis");
                return createErrorResponse("AI响应格式错误：缺少必要字段");
            }
            
            // 4. 构建AIAnalysisResponse
            AIAnalysisResponse response = new AIAnalysisResponse();
            response.setSuccess(rootNode.get("success").asBoolean());
            
            if (!response.isSuccess()) {
                String errorMessage = rootNode.has("errorMessage") ? 
                    rootNode.get("errorMessage").asText() : "AI分析失败";
                response.setErrorMessage(errorMessage);
                return response;
            }
            
            // 5. 解析语句分析结果
            List<AIStatementAnalysis> statementAnalyses = parseStatementAnalyses(rootNode.get("statementAnalysis"));
            response.setStatementAnalysis(statementAnalyses);
            
            // 6. 解析元数据
            if (rootNode.has("metadata")) {
                Map<String, Object> metadata = parseMetadata(rootNode.get("metadata"));
                response.setMetadata(metadata);
            }
            
            log.info("AI响应解析成功，共解析 {} 个语句", statementAnalyses.size());
            return response;
            
        } catch (Exception e) {
            log.error("解析AI响应时发生错误", e);
            return createErrorResponse("解析AI响应失败: " + e.getMessage());
        }
    }

    /**
     * 从原始响应中提取JSON内容
     * 支持多种格式：OpenAI API格式、markdown代码块、直接JSON、包装在content字段中等
     */
    private String extractJsonContent(String rawResponse) {
        if (rawResponse == null || rawResponse.trim().isEmpty()) {
            return null;
        }
        
        String content = rawResponse.trim();
        
        // 1. 如果是OpenAI API格式，先提取choices[0].message.content
        try {
            JsonNode apiResponseNode = objectMapper.readTree(content);
            
            // 检查是否是OpenAI格式（包含choices数组）
            if (apiResponseNode.has("choices") && apiResponseNode.get("choices").isArray() 
                && apiResponseNode.get("choices").size() > 0) {
                JsonNode firstChoice = apiResponseNode.get("choices").get(0);
                if (firstChoice.has("message") && firstChoice.get("message").has("content")) {
                    content = firstChoice.get("message").get("content").asText();
                    log.debug("从OpenAI API格式中提取content: {}", content.substring(0, Math.min(100, content.length())));
                }
            }
            // 检查是否是简单的content包装格式
            else if (apiResponseNode.has("content")) {
                content = apiResponseNode.get("content").asText();
                log.debug("从content字段中提取: {}", content.substring(0, Math.min(100, content.length())));
            }
        } catch (JsonProcessingException e) {
            // 不是JSON格式，继续其他方式处理
            log.debug("不是JSON格式的外层包装，继续解析内容");
        }
        
        // 2. 尝试从markdown代码块中提取
        Matcher codeBlockMatcher = JSON_CODE_BLOCK_PATTERN.matcher(content);
        if (codeBlockMatcher.find()) {
            String extractedJson = codeBlockMatcher.group(1).trim();
            log.debug("从markdown代码块中提取JSON: {}", extractedJson.substring(0, Math.min(100, extractedJson.length())));
            return extractedJson;
        }
        
        // 3. 尝试直接匹配JSON
        Matcher directJsonMatcher = JSON_DIRECT_PATTERN.matcher(content);
        if (directJsonMatcher.find()) {
            String extractedJson = directJsonMatcher.group().trim();
            log.debug("直接匹配JSON: {}", extractedJson.substring(0, Math.min(100, extractedJson.length())));
            return extractedJson;
        }
        
        // 4. 检查是否是纯SQL响应（包含SQL注释或语句）
        if (content.contains("--") || content.toUpperCase().matches(".*\\b(SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP)\\b.*")) {
            log.warn("检测到纯SQL响应而非JSON格式: {}", content.substring(0, Math.min(200, content.length())));
            return null; // 返回null表示无法提取有效JSON
        }
        
        // 5. 验证原内容是否为有效JSON
        try {
            objectMapper.readTree(content);
            log.debug("验证原始内容为有效JSON: {}", content.substring(0, Math.min(100, content.length())));
            return content;
        } catch (JsonProcessingException e) {
            log.warn("原始内容不是有效JSON，无法解析: {}", content.substring(0, Math.min(200, content.length())));
            return null;
        }
    }

    /**
     * 解析语句分析结果列表
     */
    private List<AIStatementAnalysis> parseStatementAnalyses(JsonNode statementArrayNode) {
        List<AIStatementAnalysis> analyses = new ArrayList<>();
        
        if (!statementArrayNode.isArray()) {
            log.warn("statementAnalysis不是数组格式");
            return analyses;
        }
        
        for (JsonNode statementNode : statementArrayNode) {
            try {
                AIStatementAnalysis analysis = parseStatementAnalysis(statementNode);
                if (analysis != null) {
                    // 对单个语句的问题进行去重合并
                    mergeIdenticalIssues(analysis);
                    analyses.add(analysis);
                }
            } catch (Exception e) {
                log.warn("解析单个语句分析时出错", e);
                // 继续处理其他语句
            }
        }
        
        return analyses;
    }

    /**
     * 合并同一语句中的同类问题
     * 同一SQL语句中相同规则ID或相同问题类型的问题只保留一条，并在描述中说明发现多处
     */
    private void mergeIdenticalIssues(AIStatementAnalysis analysis) {
        if (analysis.getIssues() == null || analysis.getIssues().isEmpty()) {
            return;
        }
        
        Map<String, AIIssueDetail> mergedIssues = new LinkedHashMap<>();
        Map<String, Integer> issueCounts = new HashMap<>();
        
        for (AIIssueDetail issue : analysis.getIssues()) {
            // 使用规则ID作为去重键，如果规则ID为空则使用规则名称
            String mergeKey = issue.getRuleId() != null ? issue.getRuleId() : 
                             (issue.getRuleName() != null ? issue.getRuleName() : issue.getDescription());
            
            if (mergeKey == null) {
                mergeKey = "UNKNOWN_" + System.nanoTime(); // 生成唯一键
            }
            
            if (mergedIssues.containsKey(mergeKey)) {
                // 已存在同类问题，增加计数
                issueCounts.put(mergeKey, issueCounts.get(mergeKey) + 1);
                
                // 合并问题片段信息（如果有新的片段）
                AIIssueDetail existingIssue = mergedIssues.get(mergeKey);
                if (issue.getProblemFragment() != null && 
                    !issue.getProblemFragment().equals(existingIssue.getProblemFragment())) {
                    
                    String combinedFragment = existingIssue.getProblemFragment() + 
                                            (existingIssue.getProblemFragment().endsWith(",") ? " " : ", ") + 
                                            issue.getProblemFragment();
                    existingIssue.setProblemFragment(combinedFragment);
                }
            } else {
                // 首次发现此类问题
                mergedIssues.put(mergeKey, issue);
                issueCounts.put(mergeKey, 1);
            }
        }
        
        // 更新问题描述，添加发现次数信息
        for (Map.Entry<String, AIIssueDetail> entry : mergedIssues.entrySet()) {
            String mergeKey = entry.getKey();
            AIIssueDetail issue = entry.getValue();
            int count = issueCounts.get(mergeKey);
            
            if (count > 1) {
                // 在描述中添加发现次数
                String originalDescription = issue.getDescription();
                String enhancedDescription = originalDescription + String.format(" (发现%d处匹配)", count);
                issue.setDescription(enhancedDescription);
                
                log.debug("合并同类问题: 规则ID={}, 原始数量={}, 合并后=1", mergeKey, count);
            }
        }
        
        // 更新语句分析的问题列表
        List<AIIssueDetail> mergedIssueList = new ArrayList<>(mergedIssues.values());
        analysis.setIssues(mergedIssueList);
        
        if (analysis.getIssues().size() < issueCounts.size()) {
            log.info("语句问题合并完成: 原始问题数={}, 合并后问题数={}", 
                    issueCounts.values().stream().mapToInt(Integer::intValue).sum(), 
                    analysis.getIssues().size());
        }
    }

    /**
     * 解析单个语句分析
     */
    private AIStatementAnalysis parseStatementAnalysis(JsonNode statementNode) {
        AIStatementAnalysis analysis = new AIStatementAnalysis();
        
        // 基本字段
        analysis.setStatementNumber(statementNode.get("statementNumber").asInt());
        analysis.setOriginalStatement(statementNode.get("originalStatement").asText());
        
        // 优化后的语句（可选）
        if (statementNode.has("optimizedStatement")) {
            analysis.setOptimizedStatement(statementNode.get("optimizedStatement").asText());
        }
        
        // 解析问题列表
        List<AIIssueDetail> issues = new ArrayList<>();
        if (statementNode.has("issues") && statementNode.get("issues").isArray()) {
            for (JsonNode issueNode : statementNode.get("issues")) {
                AIIssueDetail issue = parseIssueDetail(issueNode);
                if (issue != null) {
                    issues.add(issue);
                }
            }
        }
        analysis.setIssues(issues);
        
        return analysis;
    }

    /**
     * 解析问题详情
     */
    private AIIssueDetail parseIssueDetail(JsonNode issueNode) {
        AIIssueDetail issue = new AIIssueDetail();
        
        // 规则ID处理 - 支持各种格式
        String ruleId = issueNode.has("ruleId") ? issueNode.get("ruleId").asText() : null;
        issue.setRuleId(normalizeRuleId(ruleId));
        
        issue.setRuleName(issueNode.get("ruleName").asText());
        issue.setSeverity(issueNode.get("severity").asText());
        issue.setCategory(issueNode.get("category").asText());
        issue.setDescription(issueNode.get("description").asText());
        issue.setSuggestion(issueNode.get("suggestion").asText());
        issue.setProblemFragment(issueNode.get("problemFragment").asText());
        issue.setSuggestedFragment(issueNode.get("suggestedFragment").asText());
        
        // 置信度（可选）
        if (issueNode.has("confidence")) {
            issue.setConfidence(issueNode.get("confidence").asInt());
        }
        
        return issue;
    }

    /**
     * 规范化规则ID格式
     * 处理AI可能返回的各种规则ID格式
     */
    private String normalizeRuleId(String originalRuleId) {
        if (originalRuleId == null || originalRuleId.trim().isEmpty()) {
            return "AIAUTO";
        }
        
        String ruleId = originalRuleId.trim().toUpperCase();
        
        // 如果已经是标准格式，直接返回
        if (ruleId.matches("^(RULE\\d{3}|AIAUTO)$")) {
            return ruleId;
        }
        
        // 处理常见的变形格式
        if (ruleId.matches("^OR\\d+$")) {
            // OR004 -> RULE004
            String number = ruleId.substring(2);
            return "RULE" + String.format("%03d", Integer.parseInt(number));
        }
        
        if (ruleId.matches("^R\\d+$")) {
            // R1 -> RULE001
            String number = ruleId.substring(1);
            return "RULE" + String.format("%03d", Integer.parseInt(number));
        }
        
        // 如果包含"AUTO"关键字，转换为AIAUTO
        if (ruleId.contains("AUTO")) {
            return "AIAUTO";
        }
        
        // 其他格式，如果看起来像规则ID但格式不标准，尝试提取数字
        Pattern numberPattern = Pattern.compile("\\d+");
        Matcher matcher = numberPattern.matcher(ruleId);
        if (matcher.find()) {
            int number = Integer.parseInt(matcher.group());
            return "RULE" + String.format("%03d", number);
        }
        
        // 默认返回AIAUTO
        log.debug("无法规范化规则ID: {}，使用AIAUTO", originalRuleId);
        return "AIAUTO";
    }

    /**
     * 解析元数据
     */
    private Map<String, Object> parseMetadata(JsonNode metadataNode) {
        Map<String, Object> metadata = new HashMap<>();
        
        metadataNode.fields().forEachRemaining(entry -> {
            String key = entry.getKey();
            JsonNode value = entry.getValue();
            
            if (value.isTextual()) {
                metadata.put(key, value.asText());
            } else if (value.isNumber()) {
                metadata.put(key, value.asLong());
            } else if (value.isBoolean()) {
                metadata.put(key, value.asBoolean());
            } else {
                metadata.put(key, value.toString());
            }
        });
        
        return metadata;
    }

    /**
     * 创建错误响应
     */
    private AIAnalysisResponse createErrorResponse(String errorMessage) {
        AIAnalysisResponse response = new AIAnalysisResponse();
        response.setSuccess(false);
        response.setErrorMessage(errorMessage);
        response.setStatementAnalysis(new ArrayList<>());
        return response;
    }

    /**
     * 验证解析结果的完整性
     */
    public boolean validateParsedResponse(AIAnalysisResponse response) {
        if (response == null) {
            return false;
        }
        
        if (!response.isSuccess()) {
            return response.getErrorMessage() != null;
        }
        
        if (response.getStatementAnalysis() == null) {
            return false;
        }
        
        // 验证每个语句分析的完整性
        for (AIStatementAnalysis analysis : response.getStatementAnalysis()) {
            if (analysis.getStatementNumber() <= 0 || 
                analysis.getOriginalStatement() == null || 
                analysis.getIssues() == null) {
                return false;
            }
            
            // 验证每个问题的完整性
            for (AIIssueDetail issue : analysis.getIssues()) {
                if (issue.getRuleName() == null || 
                    issue.getSeverity() == null || 
                    issue.getDescription() == null) {
                    return false;
                }
            }
        }
        
        return true;
    }
}